﻿using System;
using System.Collections.Generic;
using System.Linq;
using FubuMVC.Core;
using FubuMVC.Core.Behaviors;
using FubuMVC.Core.Config;
using FubuMVC.Core.Runtime;
using FubuMVC.WebTestTrack.Controllers;
using FubuMVC.WebTestTrack.Views;
using StructureMap.Configuration.DSL;
using StructureMap.Pipeline;

namespace FubuMVC.WebTestTrack
{

    public class FubuMvcConfiguration : Registry
    {
        public FubuMvcConfiguration()
        {
            configureHome();
            configureTest();
        }

        private void configureHome()
        {
            var home = new UrlAction {PrimaryUrlStub = ""};
            home.AddOtherUrlStub("home");
            home.AddOtherUrlStub("home/index");
            home.AddOtherUrlStub("home/index/{Id}");

            ForConcreteType<HomeController>();
            ForRequestedType<UrlAction>().AddInstances(x => x.IsThis(home));

            var prepareInputBehavior = new ConfiguredInstance(typeof (prepare_the_input<IndexModel>));

            var controllerBehavior =
                new ConfiguredInstance(typeof (call_OMIOMO_action<HomeController, IndexModel, IndexModel>))
                    .CtorDependency<Func<HomeController, IndexModel, IndexModel>>("controllerAction").Is(
                    new Func<HomeController, IndexModel, IndexModel>((c, i) => c.Index(i)));

            var setResultBehavior = new ConfiguredInstance(typeof (render_the_view))
                .WithCtorArg("viewToRender").EqualTo("~/Views/Home/Index.aspx");

            var executeBehavior = new ConfiguredInstance(typeof (execute_the_result));

            configureInstances(home, new[] { controllerBehavior, prepareInputBehavior, setResultBehavior, executeBehavior });

        }

        private void configureTest()
        {
            var test = new UrlAction {PrimaryUrlStub = "test"};
            test.AddOtherUrlStub("test/{Name}");

            var nulloBehavior = new ConfiguredInstance(typeof (NulloBehavior));

            var prepareInputBehavior = new ConfiguredInstance(typeof(prepare_the_input<TestModel>));

            ForRequestedType<UrlAction>().AddInstances(x => x.IsThis(test));
            var setResultBehavior = new ConfiguredInstance(typeof(render_the_view))
                .WithCtorArg("viewToRender").EqualTo("~/Views/Test/Index.aspx");

            var executeBehavior = new ConfiguredInstance(typeof(execute_the_result));

            configureInstances(test, new[] { nulloBehavior, prepareInputBehavior, setResultBehavior, executeBehavior });
        }

        private void configureInstances(UrlAction action, IEnumerable<ConfiguredInstance> instances)
        {
            ConfiguredInstance behaviorInstance = null;
            instances.AsEnumerable().Each(instance =>
            {
                if (behaviorInstance != null)
                {
                    instance
                        .SetterDependency<IActionBehavior>("InsideBehavior")
                        .Is(behaviorInstance);
                }

                behaviorInstance = instance;
            });


            ForRequestedType<IFubuHttpHandler>().TheDefault.Is.OfConcreteType<FubuHttpHandler>()
                .WithName(action.UniqueId.ToString())
                .CtorDependency<UrlAction>().Is(action)
                .CtorDependency<IActionBehavior>().Is(behaviorInstance);
        }
    }
}